import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;


public class GeraRelatorio {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) {
		if(args.length == 0) {
			System.out.println("-> Parametro do arquivo fonte nao foi passado.");
			return;
		}
		File arquivoFonte = new File(args[0]);
		File arquivoDestino = new File(arquivoFonte.getParentFile(), arquivoFonte.getName() + ".csv");

		BufferedReader in;
		try {
			in = new BufferedReader(new FileReader(arquivoFonte));
		} catch (FileNotFoundException e) {
			System.out.println("-> Erro ao criar stream de leitura do arquivo fonte.");
			return;
		}
		PrintWriter out;
		try {
			out = new PrintWriter(new FileWriter(arquivoDestino));
		} catch (IOException e) {
			System.out.println("-> Erro ao criar stream de escrita do arquivo destino.");
			return;
		}
		
		Map<String, Map<String, Map<Date, String>>> mapaUsuarios = new TreeMap<String, Map<String, Map<Date, String>>>();
		DateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		DateFormat formatador = new SimpleDateFormat("yyyy-MM-dd");
		DateFormat formatador2 = new SimpleDateFormat("dd/MM");
		String menorDia = "9999-99-99";
		String maiorDia = "0000-00-00";
		
		int count = 0;
		String linha = null;
		try {
			while( (linha = in.readLine()) != null ) {
				count++;				
				String[] partes = linha.split(",");
				if(partes.length == 4) {
					String usu = partes[0];
					
					if( !mapaUsuarios.containsKey(usu) ) {
						mapaUsuarios.put(usu, new TreeMap<String, Map<Date,String>>());
					}
										
					try {
						Date data = parser.parse(partes[1]);
						String dia = formatador.format(data);
						
						if(dia.compareTo(menorDia) < 0) {
							menorDia = dia;
						}
						if(dia.compareTo(maiorDia) > 0) {
							maiorDia = dia;
						}
						
						if(!mapaUsuarios.get(usu).containsKey(dia)) {
							mapaUsuarios.get(usu).put(dia, new TreeMap<Date, String>());
						}
						
						mapaUsuarios.get(usu).get(dia).put(data, partes[3]);
						
					} catch (ParseException e) {
						System.out.println("-> Erro ao formatar data no registro " + count + ": " + partes[1]);
						return;
					}
				}
				else {
					System.out.println("-> Registro invalido na linha " + count + ": " + linha);
				}
			}
		} catch (IOException e1) {
			System.out.println("-> Erro ao ler arquivo fonte.");
			return;
		}
		
		String separador = ";";
		String[] dias = geraDias(menorDia, maiorDia, formatador);
		out.print("\"Codigo\"" + separador);
		for(String dia : dias) {
			try {
				out.print( "\"" + formatador2.format(formatador.parse(dia)) + "\"" + separador);
			} catch (ParseException e) {
				System.out.println("-> Erro ao formatar data para saida.");
				return;
			}	
		}
		out.println("\"Total horas\"");
		
		for( Map.Entry<String,Map<String,Map<Date,String>>> entry : mapaUsuarios.entrySet() ) {
			out.print( entry.getKey() + separador );
			
			BigDecimal soma = BigDecimal.ZERO;
			for(String dia : dias) {
				BigDecimal valorCelula = getValorCelula(entry.getValue().get(dia));
				if(valorCelula != null) {
					soma = soma.add(valorCelula);
					out.print(valorCelula.toString() + separador);
				}
				else {
					out.print("-" + separador);
				}
				
			}
			out.println( soma.setScale(2, BigDecimal.ROUND_HALF_UP) );
		}	
		
		try {
			in.close();
		} catch (IOException e) {
			System.out.println("-> Erro ao fechar stream de leitura do arquivo fonte.");
		}
		out.flush();
		out.close();
	}

	private static BigDecimal getValorCelula(Map<Date, String> map) {
		if(map == null) {
			return BigDecimal.ZERO;
		}
		if(map.size() == 0) {
			return BigDecimal.ZERO;
		}
		if(map.size() % 2 != 0) {
			return null; // erro
		}
		
		List<Map.Entry<Date, String>> lista = new ArrayList<Map.Entry<Date,String>>(map.entrySet());

		long soma = 0;
		for( int i = 0; i < lista.size(); i += 2 ) {
			if(!lista.get(i).getValue().equals("E") || !lista.get(i+1).getValue().equals("S")) {
				return null; // erro
			}
			
			Date a = lista.get(i).getKey();
			Date b = lista.get(i+1).getKey();
			soma += (b.getTime() - a.getTime());
		}
		return new BigDecimal(soma).divide(new BigDecimal("3600000"), 2, BigDecimal.ROUND_HALF_UP);
	}

	private static String[] geraDias(String menorDia, String maiorDia, DateFormat formatador) {
		try {
			Calendar menor = new GregorianCalendar();
			menor.setTime(formatador.parse(menorDia));
			Calendar maior = new GregorianCalendar();
			maior.setTime(formatador.parse(maiorDia));
			
			List<String> listaDias = new LinkedList<String>();
			listaDias.add(menorDia);
			menor.add(Calendar.DAY_OF_MONTH, 1);
			while( menor.compareTo(maior) <= 0 ) {
				listaDias.add( formatador.format(menor.getTime()) );
				menor.add(Calendar.DAY_OF_MONTH, 1);						
			}
			
			return listaDias.toArray(new String[0]);
			
		} catch (ParseException e) {
			System.out.println("Erro ao gerar lista de dias.");
			return new String[0];
		}
	}

}